package com.atao.baokede.websocket;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.atao.baokede.enums.Websocket;
import com.atao.baokede.pojo.MerchantMessage;
import com.atao.baokede.pojo.Dialogue;
import com.atao.baokede.service.DialogueService;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket 消息服务
 */
@Component
@ServerEndpoint("/ws/{sid}")
public class MessageServer {
    // 将 sessionMap 改为静态变量，所有实例共享
    public static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();

    // 静态变量存储Spring应用上下文
    private static DialogueService dialogueService;

    @Autowired
    public void setDialogueService(DialogueService service) {
        MessageServer.dialogueService = service;
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) {
        // 设置会话超时时间设置为72个小时
        session.setMaxIdleTimeout(3600000*72);

        // 打印更详细的连接信息
        String requestURI = session.getRequestURI().toString();
        System.out.println("聊天室WebSocket连接建立: URI=" + requestURI + ", sid=" + sid);

        /*
            商家的sid格式为："merchant_" + merchantId
            用户的sid格式为："user_" + userId
         */
        sessionMap.put(sid, session);
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     *                商家与用户对话的消息格式：{"type":"dialogue","counterpartId":"1","data":"具体消息"}
     *
     * @param sid 当前用户的sid
     */
    @OnMessage
    public void onMessage(String message, @PathParam("sid") String sid) {
        System.out.println("收到来自客户端的消息: " + sid + ":" + message);
        try {
            // 使用Hutool解析JSON字符串
            JSONObject jsonObject = JSONUtil.parseObj(message);

            // 获取消息类型
            String MessageType = jsonObject.getStr("type");
            // 处理对话消息
            if (Websocket.dialogue.name().equals(MessageType)) {
                //获取自己的id
                //先识别自己的商家还是用户
                String type = sid.split("_")[0];
                if(type.equals(Websocket.user.name())){
                    // 获取对方用户ID
                    String counterpartId = jsonObject.getStr("counterpartId");
                    // 获取消息内容
                    String data = jsonObject.getStr("data");
                    // 根据当前用户类型确定对方用户类型和sid
                    String targetSid = "merchant_" + counterpartId;

                    Dialogue dialogue = new Dialogue();
                    dialogue.setUserId(Long.parseLong(sid.split("_")[1]));
                    dialogue.setMerchantId(Long.parseLong(counterpartId));
                    dialogue.setContent(data);
                    dialogue.setSender(Websocket.user.name());

                    // 消息持久化存储
                    dialogueService.addDialogue(dialogue);
                    // 发送消息给对方
                    sendMessageToTarget(targetSid, sid, data);
                }else if(type.equals(Websocket.merchant.name())){
                    // 获取对方用户ID
                    String counterpartId = jsonObject.getStr("counterpartId");
                    // 获取消息内容
                    String data = jsonObject.getStr("data");
                    // 根据当前用户类型确定对方用户类型和sid
                    String targetSid = "user_" + counterpartId;

                    Dialogue dialogue = new Dialogue();
                    dialogue.setUserId(Long.parseLong(sid.split("_")[1]));
                    dialogue.setMerchantId(Long.parseLong(counterpartId));
                    dialogue.setContent(data);
                    dialogue.setSender(Websocket.merchant.name());

                    // 消息持久化存储
                    dialogueService.addDialogue(dialogue);
                    // 发送消息给对方
                    sendMessageToTarget(targetSid, sid, data);

                }else {
                    System.out.println("未知的用户类型");
                }


            }

        } catch (Exception e) {
            System.err.println("处理消息时发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam("sid") String sid) {
        System.out.println("聊天室WebSocket连接关闭: sid=" + sid);
        sessionMap.remove(sid);
    }

    /**
     * 群发
     */
    public synchronized void sendToAllClient(String message) {
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions) {
            if (session.isOpen()) { // 增加会话有效性判断
                try {
                    session.getBasicRemote().sendText(message);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 向指定商家发送消息，提示商家有新的消息待查看
     *
     * @param merchantId 商家ID
     * @param message    消息内容
     */
    public synchronized void sendToMerchant(String merchantId, MerchantMessage message) {
        // 构造sid格式: message_merchantId
        String sid = "merchant_" + merchantId;

        // 获取对应session
        Session session = sessionMap.get(sid);

        // 判断session是否存在且处于开启状态
        if (session != null && session.isOpen()) {
            try {
                message.setData("具体消息请到邮箱中查看");
                // 先将message转换为JSONObject
                JSONObject jsonObject = JSONUtil.parseObj(message);
                // 添加类型属性
                jsonObject.set("type", "MerchantMessage");

                // 发送JSON格式消息
                session.getBasicRemote().sendText(jsonObject.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 向指定人发送消息
     *
     * @param targetSid  目标用户的sid
     * @param senderSid  发送者的sid
     * @param message    消息内容
     */
    public synchronized void sendMessageToTarget(String targetSid, String senderSid, String message) {
        Session targetSession = sessionMap.get(targetSid);
        if (targetSession != null && targetSession.isOpen()) {
            try {
                // 创建JSON对象，将消息内容添加到对象中
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("type", "dialogue");
                jsonObject.put("sender", senderSid);
                jsonObject.put("content", message);

                // 发送JSON格式消息
                targetSession.getBasicRemote().sendText(jsonObject.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
